package com.shenfc.fxzj.config;

import com.shenfc.fxzj.shiro.AuthRealm;
import com.shenfc.fxzj.shiro.RedisCacheManager;
import com.shenfc.fxzj.shiro.RememberMeFilter;
import com.shenfc.fxzj.util.RedisUtil;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.codec.Base64;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.context.annotation.Lazy;

import javax.servlet.Filter;
import java.util.HashMap;
import java.util.Map;

/**
 * 功能:shiro配置项
 * 开发人员:shenfc
 * 创建时间:2018/8/13 0013 8:47
 * 备注:
 */
@Configuration
public class ShiroConfiguration {


    @Bean
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    /**
     * 设置是否直接代理目标类，而不是仅代理*特定接口。默认值为“ false
     */
    @Bean
    @DependsOn("lifecycleBeanPostProcessor")
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
        return defaultAdvisorAutoProxyCreator;
    }

    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager());
        return authorizationAttributeSourceAdvisor;
    }

    /**
     * 安全认证过滤器
     *
     * @return
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean() {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager());
        /*loginUrl认证提交地址，如果没有认证将会请求此地址进行认证，请求此地址将由formAuthenticationFilter进行表单认证*/
        shiroFilterFactoryBean.setLoginUrl("/adminLogin");
        /*认证成功统一跳转到first.action，建议不配置，shiro认证成功自动到上一个请求路径*/
//        shiroFilterFactoryBean.setSuccessUrl("/index");
        //错误页面，认证不通过跳转
//        shiroFilterFactoryBean.setUnauthorizedUrl("/adminLogin");
        Map<String, Filter> filters = new HashMap<String, Filter>();
        filters.put("rememberMe", rememberMeFilter());
        shiroFilterFactoryBean.setFilters(filters);
        Map<String, String> map = new HashMap<String, String>();
        //放过
        map.put("/adminLogin", "anon");
        map.put("/adminToLogin", "anon");
        /*认证*/
        map.put("/admin/**", "authc,perms");
        map.put("/admin/**", "rememberMe");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
        return shiroFilterFactoryBean;
    }

    /**
     * remeberMe过滤器
     *
     * @return
     */
    @Bean
    public RememberMeFilter rememberMeFilter() {
        RememberMeFilter rememberMeFilter = new RememberMeFilter();
        rememberMeFilter.setUsernameParam("username");
        rememberMeFilter.setPasswordParam("password");
        rememberMeFilter.setRememberMeParam("rememberMeParam");
        rememberMeFilter.setLoginUrl("/adminLogin");
        return rememberMeFilter;
    }

    /**
     * 定义Shiro安全管理配置
     */
    @Bean
    public DefaultWebSecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        /*注入角色权限管理*/
        securityManager.setRealm(authRealm());
        /*注入缓存管理器*/
        securityManager.setCacheManager(redisCacheManager());
        /*注入session管理器*/
        securityManager.setSessionManager(sessionManager());
        securityManager.setRememberMeManager(rememberMeManager());
        return securityManager;
    }

    /**
     * rememberMeManager管理器，写cookie，取出cookie生成用户信息
     *
     * @return
     */
    @Bean
    public CookieRememberMeManager rememberMeManager() {
        CookieRememberMeManager rememberMeManager = new CookieRememberMeManager();
        //rememberme cookie加密的密钥 建议每个项目都不一样 默认AES算法 密钥长度（128 256 512 位），通过以下代码可以获取
        //KeyGenerator keygen = KeyGenerator.getInstance("AES");
        //SecretKey deskey = keygen.generateKey();
        //System.out.println(Base64.encodeToString(deskey.getEncoded()));
        rememberMeManager.setCipherKey(Base64.decode("4AvVhmFLUs0KTA3Kprsdag=="));
        rememberMeManager.setCookie(rememberMeCookie());
        return rememberMeManager;
    }

    /**
     * 记住我cookie
     *
     * @return
     */
    @Bean
    public SimpleCookie rememberMeCookie() {
        /*rememberMe是cookie的名字*/
        SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
        /*jsessionId的path为 / 用于多个系统共享jsessionId*/
        simpleCookie.setPath("/");
        /*保证该系统不会受到跨域的脚本操作供给*/
        simpleCookie.setHttpOnly(true);
        /*记住我cookie生效时间30天*/
        simpleCookie.setMaxAge(2592000);
        return simpleCookie;
    }

    /**
     * 会话管理器
     *
     * @return
     */
    @Bean
    public DefaultWebSessionManager sessionManager() {
        DefaultWebSessionManager defaultWebSessionManager = new DefaultWebSessionManager();
        /*session的失效时长，单位毫秒*/
        defaultWebSessionManager.setGlobalSessionTimeout(6000000L);
        /*删除失效的session*/
        defaultWebSessionManager.setDeleteInvalidSessions(true);
        defaultWebSessionManager.setSessionIdCookie(sessionIdCookie());
        defaultWebSessionManager.setSessionIdCookieEnabled(true);
        return defaultWebSessionManager;
    }

    @Bean
    public SimpleCookie sessionIdCookie() {
        SimpleCookie simpleCookie = new SimpleCookie("BLOG_SESSION_ID");
        /*jsessionId的path为 / 用于多个系统共享jsessionId*/
        simpleCookie.setPath("/");
        /*保证该系统不会受到跨域的脚本操作供给*/
        simpleCookie.setHttpOnly(true);
        /*定义Cookie的过期时间，单位为秒，如果设置为-1表示浏览器关闭，则Cookie消失*/
        simpleCookie.setMaxAge(-1);
        return simpleCookie;
    }

    /**
     * 缓存管理器
     *
     * @return
     */
    @Bean
//    @Lazy
    public RedisCacheManager redisCacheManager() {
        RedisCacheManager redisCacheManager = new RedisCacheManager();
        return redisCacheManager;
    }

    /**
     * 自定义Realm
     *
     * @return
     */
    @Bean
    public AuthRealm authRealm() {
        AuthRealm authRealm = new AuthRealm();
//        将凭证匹配器设置到realm中，realm按照凭证匹配器的要求进行散列
        authRealm.setCredentialsMatcher(credentialsMatcher());
        return authRealm;
    }

    @Bean
    public HashedCredentialsMatcher credentialsMatcher() {
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        hashedCredentialsMatcher.setHashAlgorithmName("md5");
        hashedCredentialsMatcher.setHashIterations(1);
//        hashedCredentialsMatcher.setStoredCredentialsHexEncoded(true);
        return hashedCredentialsMatcher;
    }

    @Bean
    public RedisUtil redisUtil() {
        RedisUtil redisUtil = new RedisUtil();
        return redisUtil;
    }
}
